home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-11-19 | 13.9 KB | 580 lines | [TEXT/MPS ] |
- /*
- File: TestHashList.cp
-
- Contains: Tester for the THashList class
-
- Copyright: © 1991-1994 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #ifndef __TESTHASHLIST__
- #include "TestHashList.h"
- #endif
-
- /**********************************************************************
- ** PUBLIC Constructor/Destructor
- ***********************************************************************/
-
- Constructor(HashList)
- Destructor(HashList)
-
- #define kArraySize (sizeof(fArray)/sizeof(TDynamic*))
-
- /**********************************************************************
- ** Test methods
- ***********************************************************************/
-
- void TTestHashList :: TestIsEmpty(Boolean correct) const
- {
- if (correct)
- {
- if (!fTest->IsEmpty())
- Printf("### ERROR: IsEmpty returned false when the list was not empty\n");
- }
- else
- {
- if (fTest->IsEmpty())
- Printf("### ERROR: IsEmpty returned true when the list was empty\n");
- }
- }
-
- void TTestHashList :: TestCount(size_t shouldBe) const
- {
- size_t is = fTest->Count();
- if (is != shouldBe)
- Printf("### ERROR: Count returned %u when it should have returned %u\n",
- is, shouldBe);
- }
-
- void TTestHashList :: TestMember(short number, Boolean ifGone) const
- {
- TNumber obj(number);
- TNumber* ptr;
-
- if ((ptr = (TNumber*)fTest->Member(obj)) != NULL)
- {
- if (ifGone)
- Printf("### ERROR: Member(match) returned #%hu when it should not be present\n",
- ptr->fNumber);
- else
- if (number != ptr->fNumber)
- Printf("### ERROR: Member(match) returned #%hu when it should have returned #%hu\n",
- ptr->fNumber, number);
- else
- if (ptr != (TNumber*)fArray[number])
- Printf("### ERROR: Member(match) returned the wrong object for #%hu\n",
- ptr->fNumber);
- }
- else
- if (!ifGone)
- Printf("### ERROR: Member(match) returned no object when #%hu should have been present\n",
- number);
- if (fTest->Member(fArray[number]))
- {
- if (ifGone)
- Printf("### ERROR: Member(void*) returned TRUE when it should not be present\n");
- }
- else
- if (!ifGone)
- Printf("### ERROR: Member(void*) returned FALSE when #%hu should have been present\n",
- number);
- }
-
- /*******************************************************************************
- ** PUBLIC DoMiscTests
- ********************************************************************************/
-
- void TTestHashList::DoMiscTests(Boolean ifAll) const
- {
- HashListInfo info;
- fTest->GetHashListInfo(info);
-
- if (ifAll)
- {
- if (info.emptySlots != 0)
- Printf("### ERROR: List is full, but # empty slots is %u instead of 0\n",
- info.emptySlots);
- if (info.longestChain < 3)
- Printf("### ERROR: List is full, but longest chain came back as %u instead of at least 3\n",
- info.longestChain);
- if (info.longestChain > 5)
- Printf("### WARNING: List is full, and longest chain came back as %u\n", info.longestChain);
- }
- else
- {
- if (info.emptySlots != fTest->GetTableSize())
- Printf("### ERROR: List is empty, but # empty slots is %u instead of %u\n",
- info.emptySlots, fTest->GetTableSize());
- if (info.longestChain != 0)
- Printf("### ERROR: List is empty, but longest chain came back as %u instead of 0\n",
- info.longestChain);
- }
- }
-
- /**********************************************************************
- ** PUBLIC InitTest
- ***********************************************************************/
-
- void TTestHashList :: InitTest(BooleanParm verbose, BooleanParm, int, char**)
- {
- short idx;
- TNumberHasher* hasher = NULL;
-
- TStandardPool* pool = GetPool();
-
- if (pool == NULL)
- {
- Printf("### ERROR: There is no global pool\n");
- return;
- }
-
- for (idx = 0; idx < kArraySize; ++idx)
- fArray[idx] = NULL;
-
- fTest = NULL;
-
- TRY
- hasher = new (pool) TNumberHasher;
- if (hasher)
- fTest = new (pool) THashList(hasher, kArraySize/4);
- CATCH_ALL
- ENDTRY
-
- if (hasher == NULL)
- {
- Printf("### ERROR: Could not create TNumberHasher\n");
- return;
- }
- if (fTest == NULL)
- {
- Printf("### ERROR: Could not create THashList\n");
- delete hasher;
- return;
- }
-
- for (idx = 0; idx < kArraySize; ++idx)
- {
- TNumber* num;
- if ((num = new (pool) TNumber(idx)) == NULL)
- {
- Printf("### ERROR: Out of Memory at #%d\n", idx);
- break;
- }
- fArray[idx] = num;
- }
- if (idx == kArraySize && verbose)
- Printf("INFO: Allocated %u objects\n", kArraySize);
- }
-
- /**********************************************************************
- ** PUBLIC RunTestIteration
- ***********************************************************************/
-
- void TTestHashList :: RunTestIteration(BooleanParm verbose, BooleanParm)
- {
- short matchFirst;
- short matchLast;
- short toMatch;
- short idx, jdx;
- TNumber* ptr;
- OSErr err;
- HashListInfo info;
-
- if (verbose)
- Printf("INFO: Testing EmptyList\n");
-
- TestIsEmpty(true);
- TestCount(0);
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, true);
- DoMiscTests(false);
-
- if (verbose)
- Printf("INFO: Testing Add, Member, Count, and IsEmpty\n");
-
- for (idx = 0; idx < kArraySize; ++idx)
- {
- ptr = (TNumber*)fArray[idx];
- fTest->Add(ptr);
-
- TestIsEmpty(false);
- TestCount(idx + 1);
-
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, jdx > idx);
- }
-
- TestIsEmpty(false);
- TestCount(kArraySize);
- DoMiscTests(true);
-
- if (verbose)
- {
- fTest->GetHashListInfo(info);
- Printf("\nINFO: # empty slots = %u\n", info.emptySlots);
- Printf("INFO: # single slots = %u\n", info.singleSlots);
- Printf("INFO: # chains = %u\n", info.numChains);
- Printf("INFO: longest chain = %u\n", info.longestChain);
- Printf("INFO: avg chain = %u\n\n", info.avgChain);
- }
- if (verbose)
- Printf("INFO: Testing AddUnique, Member, Count, and IsEmpty\n");
-
- for (idx = 0; idx < kArraySize; ++idx)
- {
- ptr = (TNumber*)fArray[idx];
- err = fTest->AddUnique(ptr);
- if (err != kASLMDuplicateFoundErr)
- {
- Printf("### ERROR: AddUnique of index #%hu return error %d\n",
- idx, err);
- }
- }
-
- matchFirst = 0;
- matchLast = kArraySize - 1;
- if (verbose)
- Printf("INFO: Testing Member and Remove by pointer methods\n");
-
- for (idx = 0; idx < kArraySize; ++idx)
- {
- Boolean result;
-
- TestIsEmpty(false);
- TestCount(kArraySize - idx);
-
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, jdx < matchFirst || jdx > matchLast);
-
- if (idx & 1)
- {
- result = fTest->Remove(fArray[matchFirst]);
- toMatch = matchFirst;
- matchFirst += 1;
- }
- else
- {
- result = fTest->Remove(fArray[matchLast]);
- toMatch = matchLast;
- matchLast -= 1;
- }
- if (!result)
- Printf("### ERROR: Remove(obj) return FALSE for #%hu\n",
- toMatch);
- if (fTest->Remove(fArray[toMatch]))
- Printf("### ERROR: Remove(obj) a 2nd time returned TRUE for #%hu\n",
- toMatch);
- }
-
- TestIsEmpty(true);
- TestCount(0);
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, true);
- DoMiscTests(false);
-
- if (verbose)
- Printf("INFO: Testing AddUnique in Random order\n");
-
- fTest->RemoveAll(); // Just in case
-
- matchFirst = 0;
- matchLast = kArraySize - 1;
- for (idx = 0; idx < kArraySize; ++idx)
- {
- if (idx & 1)
- ptr = (TNumber*)fArray[matchFirst];
- else
- ptr = (TNumber*)fArray[matchLast];
- fTest->Add(ptr);
-
- TestIsEmpty(false);
- TestCount(idx + 1);
-
- for (jdx = 0; jdx < kArraySize; ++jdx)
- if (idx & 1)
- TestMember(jdx, jdx > matchFirst && jdx <= matchLast);
- else
- TestMember(jdx, jdx >= matchFirst && jdx < matchLast);
- if (idx & 1)
- matchFirst += 1;
- else
- matchLast -= 1;
- }
-
- TestIsEmpty(false);
- TestCount(kArraySize);
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, false);
- DoMiscTests(true);
- if (verbose)
- {
- fTest->GetHashListInfo(info);
- Printf("\nINFO: # empty slots = %u\n", info.emptySlots);
- Printf("INFO: # single slots = %u\n", info.singleSlots);
- Printf("INFO: # chains = %u\n", info.numChains);
- Printf("INFO: longest chain = %u\n", info.longestChain);
- Printf("INFO: avg chain = %u\n\n", info.avgChain);
- }
-
- if (verbose)
- Printf("INFO: Testing Remove by reference\n");
-
- matchFirst = (kArraySize/2) - 1;
- matchLast = kArraySize/2;
-
- for (idx = 0; idx < kArraySize; ++idx)
- {
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, jdx > matchFirst && jdx < matchLast);
- if (idx & 1)
- jdx = matchFirst;
- else
- jdx = matchLast;
-
- TestIsEmpty(false);
- TestCount(kArraySize - idx);
-
- {
- TNumber test(jdx);
- ptr = (TNumber*)fTest->Remove(test);
- if (ptr == NULL)
- Printf("ERROR: Remove for number #%u returned NULL\n", jdx);
- else
- {
- if (ptr != fArray[jdx])
- Printf("### ERROR: Remove for number #%u returned the wrong pointer\n", jdx);
- if (ptr->fNumber != jdx)
- Printf("### ERROR: Remove for number #%u return #%u\n", jdx, ptr->fNumber);
- }
- ptr = (TNumber*)fTest->Remove(test);
- if (ptr != NULL)
- Printf("### ERROR: Remove for number #%u a second time return #%u\n",
- jdx, ptr->fNumber);
- }
-
- TestCount(kArraySize - 1 -idx);
-
- if (idx & 1)
- matchFirst -= 1;
- else
- matchLast += 1;
-
- }
-
- TestIsEmpty(true);
- TestCount(0);
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, true);
- DoMiscTests(false);
-
- if (verbose)
- Printf("INFO: Testing RemoveAll\n");
-
- fTest->RemoveAll();
-
- TestIsEmpty(true);
- TestCount(0);
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, true);
-
- for (idx = 0; idx < kArraySize; ++idx)
- fTest->Add(fArray[idx]);
-
- if (verbose)
- Printf("INFO: Testing Iterator::Next()\n");
-
- Boolean saw[kArraySize];
- Boolean ok;
- TIterator* it = fTest->CreateIterator((TStandardPool*)TMemoryPool::RecoverPool(fTest));
- TNumber* num;
- memset(saw, 0, sizeof(saw));
- while ((num = (TNumber*)it->Next()) != NULL)
- {
- if (num->fNumber < 0 || num->fNumber > 99)
- Printf("ERROR: Iterator returned a #%u object\n", num->fNumber);
- else
- {
- if (saw[num->fNumber])
- Printf("ERROR: Iterator returned #%u more than once\n", num->fNumber);
- saw[num->fNumber] = true;
- }
- }
- ok = true;
- for (jdx = 0; jdx < kArraySize; ++jdx)
- if (!saw[jdx])
- {
- ok = false;
- Printf("ERROR: Iterator did not return #%u\n", jdx);
- }
-
- if (ok)
- {
- if (verbose)
- Printf("INFO: Testing Iterator::RemoveCurrentObject\n");
- it->Reset();
- memset(saw, 0, sizeof(saw));
-
- while ((num = (TNumber*)it->Next()) != NULL)
- {
- if (num->fNumber < 0 || num->fNumber > 99)
- Printf("ERROR: Iterator returned a #%u object\n", num->fNumber);
- else
- {
- if (saw[num->fNumber])
- Printf("ERROR: Iterator returned #%u more than once\n", num->fNumber);
- saw[num->fNumber] = true;
- if (!it->RemoveCurrentObject())
- Printf("ERROR: RemoveCurrentObject returned false on #%u\n", num->fNumber);
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, saw[jdx]);
- }
- }
- TestIsEmpty(true);
- TestCount(0);
- }
- if (ok && fTest->IsEmpty())
- {
- if (verbose)
- Printf("INFO: Testing Iterator::RemoveCurrentObject Randomly\n");
- for (idx = 0; idx < kArraySize; ++idx)
- fTest->Add(fArray[idx]);
-
- TestIsEmpty(false);
- TestCount(kArraySize);
-
- memset(saw, 0, sizeof(saw));
- size_t count = 0;
- TFastRandom rand;
- while (count < 100)
- {
- unsigned long kill;
- do
- {
- kill = rand.GetRandomNumber(0, 99);
- } while (saw[kill]);
-
- it->Reset();
-
- while ((num = (TNumber*)it->Next()) != NULL)
- {
- if (num->fNumber < 0 || num->fNumber > 99)
- Printf("ERROR: Iterator returned a #%u object\n", num->fNumber);
- else
- {
- if (saw[num->fNumber])
- Printf("ERROR: Iterator returned #%u more than once\n", num->fNumber);
- if (num->fNumber == kill)
- {
- ++count;
- saw[num->fNumber] = true;
- if (!it->RemoveCurrentObject())
- Printf("ERROR: RemoveCurrentObject returned false on #%u\n", num->fNumber);
- for (jdx = 0; jdx < kArraySize; ++jdx)
- TestMember(jdx, saw[jdx]);
- }
- }
- }
- }
- }
- if (ok && fTest->IsEmpty())
- {
- size_t todo = fTest->GetTableSize() + fTest->GetTableSize()/2;
- if (verbose)
- Printf("INFO: Testing Iterator::RemoveCurrentObject Randomly with mixed chains\n");
- for (idx = 0; idx < todo; ++idx)
- fTest->Add(fArray[idx]);
-
- TestIsEmpty(false);
- TestCount(todo);
- if (verbose)
- {
- fTest->GetHashListInfo(info);
- Printf("\nINFO: # empty slots = %u\n", info.emptySlots);
- Printf("INFO: # single slots = %u\n", info.singleSlots);
- Printf("INFO: # chains = %u\n", info.numChains);
- Printf("INFO: longest chain = %u\n", info.longestChain);
- Printf("INFO: avg chain = %u\n\n", info.avgChain);
- }
-
- memset(saw, 0, sizeof(saw));
- size_t count = 0;
- TFastRandom rand;
- while (count < todo)
- {
- size_t kill;
- do
- {
- kill = size_t(rand.GetRandomNumber(0, todo - 1));
- } while (saw[kill]);
-
- it->Reset();
-
- while ((num = (TNumber*)it->Next()) != NULL)
- {
- if (num->fNumber < 0 || num->fNumber > todo - 1)
- Printf("ERROR: Iterator returned a #%u object\n", num->fNumber);
- else
- {
- if (saw[num->fNumber])
- Printf("ERROR: Iterator returned #%u more than once\n", num->fNumber);
- if (num->fNumber == kill)
- {
- ++count;
- saw[num->fNumber] = true;
- if (!it->RemoveCurrentObject())
- Printf("ERROR: RemoveCurrentObject returned false on #%u\n", num->fNumber);
- for (jdx = 0; jdx < todo; ++jdx)
- TestMember(jdx, saw[jdx]);
- }
- }
- }
- }
- }
- delete it;
-
- TestIsEmpty(true);
- TestCount(0);
- if (fTest->IsEmpty())
- {
- for (idx = 0; idx < kArraySize; ++idx)
- fTest->Add(fArray[idx]);
-
- TestIsEmpty(false);
- TestCount(kArraySize);
- if (verbose)
- Printf("INFO: Testing DeleteAll\n");
-
- fTest->DeleteAll(kTDynamicPointer);
-
- TestIsEmpty(true);
- TestCount(0);
- }
-
- for (jdx = 0; jdx < kArraySize; ++jdx)
- {
- TNumber foo(jdx);
- if (!fTest->Member(foo))
- fArray[jdx] = NULL;
- else
- Printf("ERROR: Member #%u still seems to exists\n", jdx);
- }
- DoMiscTests(false);
- }
-
- /**********************************************************************
- ** PUBLIC EndTest
- ***********************************************************************/
-
- void TTestHashList :: EndTest(BooleanParm verbose, BooleanParm)
- {
- if (verbose)
- Printf("INFO: End of HashList test\n");
- TNumberHasher* hasher = (TNumberHasher*)fTest->GetHashObject();
- delete hasher;
- for (short idx = 0; idx < kArraySize; ++idx)
- {
- TDynamic* obj = fArray[idx];
- delete obj;
- }
- }
-